﻿using Avalonia.Controls;
using Avalonia.Media;
using Avalonia.Remote.Protocol;
using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using LightCAD.Three;
using SkiaSharp;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;


namespace LightCAD.Drawing
{
    public class DimDiameterAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;

        static DimDiameterAction()
        {
            CommandName = "DIMDIAMETER";
            CreateMethods = new LcCreateMethod[1];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "DDI",
                Description = "DIMDIAMETER",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep{ Name="Step0", Options="选择圆或圆弧:" },
                }
            };
            
        }

        internal static void Initilize()
        {
            ElementActions.DimDiametric = new DimDiameterAction();
            LcDocument.ElementActions.Add(BuiltinElementType.DimDiametric, ElementActions.DimDiametric);
        }

        private PointInputer inputer { get; set; }

        private Vector2d point;
        private Vector2d endpoint;
        private Vector2d center;
        private double raduis;
    
        public DimDiameterAction() { }
        public DimDiameterAction(DocumentRuntime docRt) : base(docRt)
        {
            docRt.CommandCtrl.WriteInfo("命令 ：DDI");
        }
        private LcCreateMethod GetMethod(string method)
        {
            if (method == null) return CreateMethods[0];
            var getted= CreateMethods.FirstOrDefault((m) => m.Name == method);
            if (getted == null)
                return CreateMethods[0];
            else
                return getted;
        }
        public async void ExecCreate(string[] args = null)
        {
            this.StartCreating();
            //this.Segments = new List<RolineSegment>();
            var curMethod = CreateMethods[0];
            var ElementInputer = new ElementInputer(this.docRt);
            this.inputer = new PointInputer(this.docRt);
            Step0:
            var step0 = curMethod.Steps[0];


            var result0 = await ElementInputer.Execute(step0.Options);
            if (ElementInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.Value == null)
            {
                goto Step0;
            }
            else
            {
                LcElement element = (LcElement)result0.Value;
                this.point = (Vector2d)result0.Extent;
                if (CreateSelects(element))
                {
                    //记住圆的圆心点 以及半径
                    if (element is LcCircle)
                    {

                        var circle = element as LcCircle;
                        this.center = circle.Center;
                        this.raduis = circle.Radius;

                        #region
                        LcLine lcline = new LcLine(circle.Center, this.point);
                        //需要移动的向量方向
                        Vector2d direction = new Vector2d();
                        //需要移动的距离
                        double dis = Math.Abs(lcline.Length - this.raduis);
                        if (lcline.Length > this.raduis)
                        {
                            //向内延伸
                            direction = new Vector2d(this.center.X - this.point.X, this.center.Y - this.point.Y);
                        }
                        else if (lcline.Length < this.raduis)
                        {
                            //向外部延伸
                            direction = new Vector2d(this.point.X - this.center.X, this.point.Y - this.center.Y);
                        }
                        if (direction.Length != 0)
                        {
                            //新的移动后的点位
                            Vector2d lidisptpos = this.point + (new Vector2d(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                            this.point = lidisptpos;
                        }
                        #endregion

                        this.endpoint = PointRotate(center, this.point, 180);

                        //将数据加入到element中
                        //this.vportRt.ActiveElementSet.AddDimDiametric(this.point, endpoint, raduis.ToString());
                        CreateDimElement();
                        goto End;

                    }
                }
                else
                {
                    goto Step0;
                }
            }
  
            End:
            this.EndCreating();

        }
        private void CreateDimElement()
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("DimDiameter");
            var DimDiametric = doc.CreateObject<DimDiametric>();
            DimDiametric.Start = this.point;
            DimDiametric.End = this.endpoint;
            DimDiametric.Dimtext =(this.raduis*2).ToString("0.00");
            DimDiametric.Center = this.center;
            doc.ModelSpace.InsertElement(DimDiametric);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
        }
       

        /// <summary>
        /// 选中的对象
        /// </summary>
        /// <param name="elements"></param>
        /// <returns></returns>
        private bool CreateSelects(LcElement elements)
        {

         
                if (elements is LcCircle|| elements is LcArc) {
                    return true;

                }
               
            return false;

        }


        /// <summary>
        /// 对一个坐标点按照一个中心进行旋转
        /// </summary>
        /// <param name="center">中心点</param>
        /// <param name="p1">要旋转的点</param>
        /// <param name="angle">旋转角度，笛卡尔直角坐标</param>
        /// <returns></returns>
        private Vector2d PointRotate(Vector2d center, Vector2d p1, double angle)
        {
            Vector2d tmp = new Vector2d();
            double angleHude = angle * Math.PI / 180;/*角度变成弧度*/
            double x1 = (p1.X - center.X) * Math.Cos(angleHude) + (p1.Y - center.Y) * Math.Sin(angleHude) + center.X;
            double y1 = -(p1.X - center.X) * Math.Sin(angleHude) + (p1.Y - center.Y) * Math.Cos(angleHude) + center.Y;
            tmp.X = (int)x1;
            tmp.Y = (int)y1;
            return tmp;
        }
        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
       
        

        public override void CreateElement(LcElement element, Matrix3d matrix)
        {
            //DocumentManager.CurrentRecorder.BeginAction("Circle");
            //var dim = element as DimDiametric;
            //this.vportRt.ActiveElementSet.AddDimDiametric(matrix.MultiplyPoint(dim.Start), matrix.MultiplyPoint(dim.End),dim.Dimtext);
            //DocumentManager.CurrentRecorder.EndAction();
        }
        public override void CreateElement(LcElement element,Vector2d basePoint, double scaleFactor)
        {
            //var circle = element as LcCircle;
            //Matrix3d matrix3 = Matrix3d.Scale(scaleFactor, basePoint);
            //this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * scaleFactor);
        }
        public override void CreateElement(LcElement element, Vector2d basePoint, Vector2d scaleVector)
        {
            //var circle = element as LcCircle;
            //Matrix3d matrix3 = Matrix3d.Scale(scaleVector, basePoint);
            //this.vportRt.ActiveElementSet.AddCircle(matrix3.MultiplyPoint(circle.Center), circle.Radius * Vector2d.Distance(basePoint, scaleVector));
        }
        public override void Draw(SKCanvas canvas, LcElement element, Matrix3d matrix)
        {
            var dim = element as DimDiametric;
          
          
            var mstart= matrix.MultiplyPoint(dim.Start);
            var mend = matrix.MultiplyPoint(dim.End);
            var mtext =  dim.Dimtext;
            var start = this.vportRt.ConvertWcsToScr(mstart).ToSKPoint();
            var end= this.vportRt.ConvertWcsToScr(mend).ToSKPoint();
            //get Layer color 
            //bool isDragCopy = (matrix != Matrix3d.Zero);
            var pen = this.GetDrawPen(dim);
            if (pen == Runtime.Constants.defaultPen)
            {
                //TODO:这里可以考虑将实线用颜色做KEY，对SKPaint进行缓存
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {

                    
                    canvas.DrawLine(start,end, elePen);
                    using (var paint = new SKPaint())
                    {
                       
                        paint.TextSize = (float)this.vportRt.Viewport.Scale*200 ;
                        paint.IsAntialias = false;
                        paint.Color = new SKColor(0x42, 0x81, 0xA4);
                        paint.IsStroke = false;

                        canvas.DrawText(mtext, start.X, start.Y, paint);
                        // canvas.RotateDegrees(50);
                    }
                    
                    //canvas.Scale()
                    //canvas.DrawText(mtext, start1, elePen);
                }
            }
            else
            {
                canvas.DrawLine(start,end, pen);
                //r
                using (var paint = new SKPaint())
                {
                    paint.TextSize = (float)this.vportRt.Viewport.Scale * 200;
                    paint.IsAntialias = false;
                    paint.Color = new SKColor(0x42, 0x81, 0xA4);
                    paint.IsStroke = false;


                    canvas.DrawText(mtext, start, paint);
                }
                //canvas.DrawText(mtext, start1, pen);
            }
            #region
            var path = DrawArrow(dim.Start, dim.End);
            var path1 = DrawArrow(dim.End, dim.Start);
            using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
            {
                //elePen.Color = SKColors.Red;
                elePen.Style = SKPaintStyle.StrokeAndFill;
                elePen.IsAntialias = true;
                elePen.StrokeWidth = 2;
                //绘制路径
                canvas.DrawPath(path, elePen);
                canvas.DrawPath(path1, elePen);
            }
            #endregion

        }
        //public override void Scale(Vector2d basePoint, double scaleFactor)
        //{
        //    Matrix3d matrix3 = Matrix3d.Scale(scaleFactor, basePoint);
        //    //this.Set(matrix3.MultiplyPoint(this.point), matrix3.MultiplyPoint(this.endpoint));
           
        //}
        private SKPath DrawArrow(Vector2d start, Vector2d end, double extraAngle = 0)
        {
            LcLine lcline = new LcLine();
            lcline.Start = start;
            lcline.End = end;
            var radian = lcline.Angle;

            var startve = new Vector2d(lcline.Start.X, lcline.Start.Y);
            var arrowtwove = new Vector2d(lcline.Start.X + 100, lcline.Start.Y + 30);
            var arrowendve = new Vector2d(lcline.Start.X + 100, lcline.Start.Y - 30);
            var angle = Utils.RadianToDegree(radian) + extraAngle;
            arrowtwove = Vector2d.Rotate(arrowtwove, startve, angle);
            arrowendve = Vector2d.Rotate(arrowendve, startve, angle);

            var pointone = this.vportRt.ConvertWcsToScr(startve).ToSKPoint();
            var pointtwo = this.vportRt.ConvertWcsToScr(arrowtwove).ToSKPoint();
            var pointthree = this.vportRt.ConvertWcsToScr(arrowendve).ToSKPoint();

            var path = new SKPath();
            path.FillType = SKPathFillType.EvenOdd;
            //外圈 顺时针
            path.MoveTo((float)pointone.X, (float)pointone.Y);    //起点
            path.LineTo((float)pointtwo.X, (float)pointtwo.Y);
            path.LineTo((float)pointthree.X, (float)pointthree.Y);
            path.Close();
            return path;
        }


        public override void DrawAuxLines(SKCanvas canvas)
        {
            //var mp = this.vportRt.PointerMovedPosition.ToVector2d();
            //var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
            //DrawAuxLine(canvas, mp, wcs_mp);

        }

        private void DrawAuxLine(SKCanvas canvas, Vector2d p0, Vector2d p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, Runtime.Constants.auxElementPen);
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }
        #region Grip
        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var dim = element as DimDiametric;

            var grips = new List<ControlGrip>();
            var gripStartr = new ControlGrip
            {
                Element = dim,
                Name = "Start",
                Position = dim.Start
            };
            grips.Add(gripStartr);

            var gripEnd = new ControlGrip
            {
                Element = dim,
                Name = "End",
                Position = dim.End
            };
            grips.Add(gripEnd);


            return grips.ToArray();
        }
        private string _gripName;
        private Vector2d _position;
        private DimDiametric _dim;

        public override void SetDragGrip(LcElement element, string gripName, Vector2d position, bool isEnd)
        {
            var dim= element as DimDiametric;

            _dim = dim;
            if (!isEnd)
            {
                _gripName = gripName;
                _position = position;
            }
            else
            {
                if (gripName == "Start")
                    dim.Set(Start: position);
                else
                {
                    //var r = Vector2d.Distance(circle.Center, position);
                    dim.Set(End: position);
                }
            }
        }


        public override void DrawDragGrip(SKCanvas canvas)
        {
            if (_dim == null) return;


            var start = this.vportRt.ConvertWcsToScr(_dim.Start);
            var end = this.vportRt.ConvertWcsToScr(_dim.End);
            double diameter = 0;
            if (_gripName == "Start") {
                //end = PointRotate(_dim.Center, _dim.Start, 180);
                start = this.vportRt.ConvertWcsToScr(_position);
                diameter = distance(_position, _dim.End);
            }
                

            
            if (_gripName == "End") {
                //start = PointRotate(_dim.Center, _dim.End, 180);
                end = this.vportRt.ConvertWcsToScr(_position);
                diameter = distance(_dim.Start, _position);
            }
            

            canvas.DrawLine(start.ToSKPoint(), end.ToSKPoint(), Runtime.Constants.draggingPen);
            using (var paint = new SKPaint())
            {
                paint.TextSize = (float)this.vportRt.Viewport.Scale * 200;
                paint.IsAntialias = false;
                paint.Color = new SKColor(0x42, 0x81, 0xA4);
                paint.IsStroke = false;


                canvas.DrawText(diameter.ToString("0.00"), start.ToSKPoint(), paint);
            }
        }

        #endregion
        public static double distance(Vector2d p1, Vector2d p2)
        {
            double result = 0;
            result = Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
            return result;

        }
        public override List<PropertyObserver> GetPropertyObservers()
        {
            return new List<PropertyObserver>();
            //{
            //    new PropertyObserver()
            //    {
            //        Name = "CenterX",
            //        DisplayName = "圆心 X 坐标",
            //        Getter = (ele) => Math.Round((ele as LcCircle).Center.X, 4),
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var x = Convert.ToDouble(value);
            //            var cen = new Vector2d(x, circle.Center.Y);
            //            circle.Set(center : cen);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "CenterY",
            //        DisplayName = "圆心 Y 坐标",
            //        Getter = (ele) => Math.Round((ele as LcCircle).Center.Y, 4),
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var y = Convert.ToDouble(value);
            //            var cen = new Vector2d(circle.Center.X, y);
            //            circle.Set(center : cen);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "Radius",
            //        DisplayName = "半径",
            //        Getter = (ele) => Math.Round((ele as LcCircle).Radius, 4),
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var radius = Convert.ToDouble(value);
            //            circle.Set(radius : radius);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "Diameter",
            //        DisplayName = "直径",
            //        Getter = (ele) => Math.Round((ele as LcCircle).Radius * 2, 4),
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var radius = Convert.ToDouble(value) / 2;
            //            circle.Set(radius : radius);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "Circumference",
            //        DisplayName = "周长",
            //        Getter = (ele) => Math.Round((ele as LcCircle).Radius * 2 * Math.PI, 4),
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var radius = Convert.ToDouble(value) / 2 / Math.PI;
            //            circle.Set(radius : radius);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "Area",
            //        DisplayName = "面积",
            //        Getter = (ele) =>
            //        {
            //            var radius = (ele as LcCircle).Radius;
            //            return Math.Round(Math.Pow(radius, 2) * Math.PI, 4);
            //        },
            //        Setter = (ele, value) =>
            //        {
            //            var circle = (ele as LcCircle);
            //            var area = Convert.ToDouble(value);
            //            var radius = Math.Sqrt(area / Math.PI);
            //            circle.Set(radius : radius);
            //        }
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "NormalX",
            //        DisplayName = "法向 X 坐标",
            //        Getter = (ele) => 0
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "NormalY",
            //        DisplayName = "法向 Y 坐标",
            //        Getter = (ele) => 0
            //    },
            //    new PropertyObserver()
            //    {
            //        Name = "NormalZ",
            //        DisplayName = "法向 Z 坐标",
            //        Getter = (ele) => 1
            //    },
            //};
        }
    }
}
